﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.Configuration;

namespace Sparrow.Web.Router.Providers
{
    [Export("default",typeof(IWebRouterProvider))]
    [PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
    public class MSSQLProvider : IWebRouterProvider
    {
        public MSSQLProvider()
        {
            var connection = ConfigurationManager.ConnectionStrings["Sparrow"];
            if (connection == null)
            {
                throw new KeyNotFoundException("Sparrow in ConnectionStrings");
            }
            this.DataContext = new WebRouterDataContext(connection.ConnectionString);   
        }

        WebRouterDataContext DataContext
        {
            get;
            set;
        }

        #region IWebRouterProvider Members

        public bool Add(Sparrow.Web.Router.WebRouter router)
        {
            if (router == null ||  this.DataContext.Routers.Any(i => i.Id == router.Id))
            {
                return false;
            }
            else
            {
                router.Id = Guid.NewGuid().ToString();

                var item = new Router()
                {
                    Id = router.Id,
                    Name = router.Name,
                    RoutePath = router.RoutePath,
                    Sequence = router.Sequence
                };

                if (router.ParentRouter == null)
                {
                    item.ParentId = null;
                }
                else
                {
                    item.ParentId = router.ParentRouter.Id;
                }


                this.DataContext.Routers.InsertOnSubmit(item);

                this.DataContext.SubmitChanges();

                return true;
            }
        }

        public bool Remove(Sparrow.Web.Router.WebRouter router)
        {
            if (router == null)
            {
                return true;
            }
            else
            {
                var item = this.DataContext.Routers.FirstOrDefault(i => i.Id == router.Id);
                if (item == null)
                {
                    return true;
                }
                else
                {
                    this.DataContext.Routers.DeleteOnSubmit(item);
                    this.DataContext.SubmitChanges();

                    return true;
                }
            }
        }

        public bool Update(Sparrow.Web.Router.WebRouter router)
        {
            if (router == null)
            {
                return false;
            }
            else
            {
                var item = this.DataContext.Routers.FirstOrDefault(i => i.Id == router.Id);
                if (item == null)
                {
                    return false;
                }
                else
                {
                    item.Name = router.Name;
                    item.Sequence = router.Sequence;
                    item.RoutePath = router.RoutePath;

                    if (router.ParentRouter == null)
                    {
                        item.ParentId = null;
                    }
                    else
                    {
                        item.ParentId = router.ParentRouter.Id;
                    }

                    this.DataContext.SubmitChanges();
                    return true;
                }
            }
        }

        public IQueryable<Sparrow.Web.Router.WebRouter> Routers()
        {
            return this.DataContext.Routers
                .Select(i => new Sparrow.Web.Router.WebRouter
                {
                    Id = i.Id,
                    Name= i.Name,
                    Sequence = i.Sequence,
                    RoutePath = i.RoutePath
                });
        }

        public IQueryable<Sparrow.Web.Router.WebRouter> RootRouters()
        {
            return this.DataContext.Routers
                .Where(i => i.ParentId == null)
                .Select(i => new Sparrow.Web.Router.WebRouter
                {
                    Id = i.Id,
                    Name = i.Name,
                    Sequence = i.Sequence,
                    RoutePath = i.RoutePath
                });
        }

        public IQueryable<Sparrow.Web.Router.JumpableWebRouter> JumpableRouters(Sparrow.Web.Router.WebRouter router)
        {
            var query = from j in this.DataContext.JumpableRouters.Where(i => i.RouterId == router.Id)
                        join r in this.DataContext.Routers
                        on j.TargetRouterId equals r.Id into list

                        from i in list.DefaultIfEmpty()
                        select new Sparrow.Web.Router.JumpableWebRouter
                        {
                            RouterModule = new WebRouterModule()
                            {
                                Name = j.RouterModuleName
                            },
                            TargetRouter = new Sparrow.Web.Router.WebRouter()
                            {
                                Id = i.Id,
                                Name = i.Name,
                                Sequence = i.Sequence,
                                RoutePath = i.RoutePath
                            }
                        };

            return query;
        }

        public IQueryable<Sparrow.Web.Router.WebRouterModule> RouterModules(Sparrow.Web.Router.WebRouter router)
        {
            return this.DataContext.RouterModules
                .Where(i => i.RouterId == router.Id)
                .Select(i => new Sparrow.Web.Router.WebRouterModule
                {
                    Name = i.RouterModuleName
                });
        }

        public IQueryable<Sparrow.Web.Router.WebRouter> Routers(Sparrow.Web.Router.WebRouterModule routerModule)
        {
            return this.DataContext.RouterModules
                .Where(i => i.RouterModuleName == routerModule.Name)
                .Select(i => new Sparrow.Web.Router.WebRouter
                {
                    Id = i.Router.Id,
                    Name = i.Router.Name,
                    Sequence = i.Router.Sequence,
                    RoutePath = i.Router.RoutePath
                });
        }

        public Sparrow.Web.Router.WebRouter ParentRouter(Sparrow.Web.Router.WebRouter router)
        {
            return this.DataContext.Routers
                .Where(i => i.ParentId == router.Id)
                .Select(i => new Sparrow.Web.Router.WebRouter
                {
                    Id = i.Id,
                    Name = i.Name,
                    Sequence = i.Sequence,
                    RoutePath = i.RoutePath
                })
                .FirstOrDefault();
        }

        public bool AddRouterModule(Sparrow.Web.Router.WebRouter router, Sparrow.Web.Router.WebRouterModule routerModule)
        {
            if (this.DataContext.RouterModules.Any(i => i.RouterId == router.Id && i.RouterModuleName == routerModule.Name))
            {
                return true;
            }
            else
            {
                var item = new RouterModule()
                {
                    RouterId = router.Id,
                    RouterModuleName = routerModule.Name
                };

                this.DataContext.RouterModules.InsertOnSubmit(item);
                this.DataContext.SubmitChanges();

                return true;
            }
        }

        public bool RemoveRouterModule(Sparrow.Web.Router.WebRouter router, Sparrow.Web.Router.WebRouterModule routerModule)
        {
            var item = this.DataContext.RouterModules.Where(i => i.RouterId == router.Id && i.RouterModuleName == routerModule.Name).FirstOrDefault();
            if (item == null)
            {
                return true;
            }
            else
            {
                this.DataContext.RouterModules.DeleteOnSubmit(item);
                this.DataContext.SubmitChanges();

                return true;
            }
        }

        public bool Add(Sparrow.Web.Router.WebRouter router, Sparrow.Web.Router.JumpableWebRouter jumpableRouter)
        {
            if (this.DataContext.JumpableRouters.Any(i => i.RouterId == router.Id && i.RouterModuleName == jumpableRouter.RouterModule.Name && i.TargetRouterId == jumpableRouter.TargetRouter.Id))
            {
                return true;
            }
            else
            {
                var item = new JumpableRouter
                {
                    RouterId = router.Id,
                    RouterModuleName = jumpableRouter.RouterModule.Name,
                    TargetRouterId = jumpableRouter.TargetRouter.Id
                };

                this.DataContext.JumpableRouters.InsertOnSubmit(item);

                this.DataContext.SubmitChanges();

                return true;
            }

        }

        public bool Remove(Sparrow.Web.Router.WebRouter router, Sparrow.Web.Router.JumpableWebRouter jumpableRouter)
        {
            var item = this.DataContext.JumpableRouters
                .Where(i => i.RouterId == router.Id && i.RouterModuleName == jumpableRouter.RouterModule.Name && i.TargetRouterId == jumpableRouter.TargetRouter.Id)
                .Select(i => i)
                .FirstOrDefault();

            if (item == null)
            {
                return true;
            }
            else
            {
                this.DataContext.JumpableRouters.DeleteOnSubmit(item);
                this.DataContext.SubmitChanges();

                return true;
            }
        }

    
        public IQueryable<WebRouter> ChildRouters(WebRouter webRouter)
        {
            return this.DataContext.Routers
              .Where(i => i.ParentId == webRouter.Id)
              .Select(i => new Sparrow.Web.Router.WebRouter
              {
                  Id = i.Id,
                  Name = i.Name,
                  Sequence = i.Sequence,
                  RoutePath = i.RoutePath
              });
        }

        #endregion
    }
}
